module ifu
(
    input   wire                clk,
    input   wire                rstn,
    //  pipeline ctrl
    input   wire                IFF_IFS_stall_i,
    input   wire                IFF_IFS_flush_i,
    //  pcReg
    input   wire                ifu_pc_hold_i,
    input   wire                ifu_jalr_flag_i, 
    input   wire                ifu_jal_flag_i,  
    input   wire    [63:00]     ifu_jump_addr_i, 
    
    input   wire                ifu_branch_flag_i,                    
    input   wire                ifu_branch_predic_fault_i,                  
    input   wire    [63:00]     ifu_branch_reserve_addr_i,
    input   wire                ifu_exc_irq_flag_i,
    input   wire    [63:00]     ifu_exc_irq_srv_prog_addr_i,            
    input   wire                ifu_mret_i,
    input   wire    [63:00]     ifu_mepc_i,
    output  wire    [63:00]     ifu_fetch_addr_o,         //  取指的PC                       
    //  从存储器取到的指令
    input   wire    [31:00]     ifu_instr_i,
    output  wire                ifu_bubble_flag_o,
    output  wire    [63:00]     ifu_instr_pc_o,         //  发送到流水线的PC
    output  wire    [31:00]     ifu_instr_o             //  发送到流水线的instr

);
//  -----------------------------------------wire----------------------------------------------------------------   
    //  pcReg
    wire    [63:00]     pcReg_pc;
    //  IFF_IFS
    wire    [31:00]     IFF_IFS_INSTR_o;
    wire                IFF_IFS_FLUSH_FLAG_o;
    wire                IFF_IFS_STALL_FLAG_o;

//--------------------------------------------------------------------------------------------------------------   
    //  pcReg
    pcReg                                                               pcReg
    (
        .clk                                                            (clk),
        .rstn                                                            (rstn),
        .pc_hold                                                        (ifu_pc_hold_i),
        //
        .branch_flag                                                    (ifu_branch_flag_i),
        .branch_predic_fault                                            (ifu_branch_predic_fault_i),
        .branch_reserve_addr                                            (ifu_branch_reserve_addr_i),
        //
        .jal_flag                                                       (ifu_jal_flag_i),
        .jalr_flag                                                      (ifu_jalr_flag_i),
        .jump_addr                                                      (ifu_jump_addr_i),   
        //
        .exc_irq_flag                                                   (ifu_exc_irq_flag_i              ),
        .exc_irq_srv_prog_addr                                          (ifu_exc_irq_srv_prog_addr_i),            
        .mret                                                           (ifu_mret_i                              ),
        .mepc                                                           (ifu_mepc_i                              ),
        //
        .pc                                                             (pcReg_pc)
    );

    //  IFF_IFS
    IFF_IFS                                                             IFF_IFS
    (
        .clk                                                            (clk),
        .rstn                                                            (rstn),
        .stall                                                          (IFF_IFS_stall_i),
        .flush                                                          (IFF_IFS_flush_i),
        .IFF_IFS_PC_i                                                   (pcReg_pc),                             // pcReg -- pc
        .IFF_IFS_INSTR_i                                                (ifu_instr_i),                          // itcm  -- instr
        .IFF_IFS_PC_o                                                   (ifu_instr_pc_o),
        .IFF_IFS_INSTR_o                                                (IFF_IFS_INSTR_o),
        .IFF_IFS_FLUSH_FLAG_o                                           (IFF_IFS_FLUSH_FLAG_o),         // 如果出现flush，则下次IF/ID寄存器接收的指令应该为NOP
        .IFF_IFS_STALL_FLAG_o                                          	(IFF_IFS_STALL_FLAG_o)          // 
); 
    assign  ifu_bubble_flag_o       =   IFF_IFS_FLUSH_FLAG_o;
    assign  ifu_fetch_addr_o        =   pcReg_pc;
    assign  ifu_instr_o             =   (IFF_IFS_FLUSH_FLAG_o || IFF_IFS_STALL_FLAG_o)   ? IFF_IFS_INSTR_o : ifu_instr_i; 
endmodule